# config_manager.py - 配置管理器

# ==================== 配置项说明 ====================

# 本文件负责管理系统中所有配置项的读取和解析工作
# 配置项包括但不限于：
# - 数据库连接信息
# - API密钥
# - 文件路径
# - 其他系统参数

# 配置项的具体含义和使用方式请参考相应的技术文档和代码注释

# ==================== 配置项加载机制 ====================

import json
import os
from typing import Any, Dict, List, Optional, Union
from .constants_v2 import CONFIG_REGISTRY, ALL_FIELD_CONFIG_REGISTRY

class ConfigManager:
    """
    配置管理器
    
    功能：
    1. 统一配置访问接口
    2. 配置验证和缓存
    3. 动态配置加载
    """
    
    def __init__(self):
        """初始化配置管理器"""
        # 导入constants_v2配置
        try:
            from backend.config import constants_v2
            self.constants_v2 = constants_v2
        except ImportError as e:
            raise ImportError(f"无法导入constants_v2配置: {e}")

        self._config_cache = {}
        
        # ✅更新：完整的表映射（全部使用复数表名作为标准）
        self._table_class_mapping = {
            # 主表映射
            'students': 'Student',
            'student_extensions': 'StudentExtension',
            'vision_records': 'VisionRecord',
            'intervention_records': 'InterventionRecord',
            'followup_records': 'FollowupRecord',
            'users': 'User',
            # 日志表映射
            'vision_record_logs': 'VisionRecordLog',
            'intervention_record_logs': 'InterventionRecordLog',
            'followup_record_logs': 'FollowupRecordLog',
            'student_archive_logs': 'StudentArchiveLog',
            # 向后兼容（单数形式，逐步废弃）
            'student': 'Student',
            'student_extension': 'StudentExtension',
            'vision_record': 'VisionRecord',
            'intervention_record': 'InterventionRecord',
            'followup_record': 'FollowupRecord',
            'user': 'User'
        }
    
    def get_table_class(self, table_name: str):
        """
        获取表名对应的SQLAlchemy模型类
        
        Args:
            table_name: 表名
            
        Returns:
            SQLAlchemy模型类
            
        Raises:
            ValueError: 未知的表名
        """
        if table_name not in self._table_class_mapping:
            raise ValueError(f"未知的表名: {table_name}")
            
        class_name = self._table_class_mapping[table_name]
        
        # 动态导入对应的模型类
        if class_name == 'Student':
            from backend.models.student import Student
            return Student
        elif class_name == 'StudentExtension':
            from backend.models.student_extension import StudentExtension
            return StudentExtension
        elif class_name == 'VisionRecord':
            from backend.models.vision import VisionRecord
            return VisionRecord
        elif class_name == 'InterventionRecord':
            from backend.models.intervention import InterventionRecord
            return InterventionRecord
        else:
            raise ValueError(f"未实现的模型类: {class_name}")
        
    def get_config(self, key: str, default: Any = None) -> Any:
        """
        获取配置项（无兜底极简版，只查CONFIG_REGISTRY）
        
        Args:
            key: 配置项键名
            default: 默认值（仅用于显式传参）
            
        Returns:
            配置项值
            
        Raises:
            KeyError: 配置项未注册
        """
        from backend.config.constants_v2 import CONFIG_REGISTRY, GLOBAL_OPTIONS_CONFIG
        
        # 动态生成被清理的重复配置（保持向后兼容）
        if key == "FIXED_METRICS":
            # 🔧 修复：直接从CONFIG_REGISTRY获取，不再硬编码
            return CONFIG_REGISTRY.get("FIXED_METRICS", [])
        elif key == "INTERVENTION_SUBFIELDS":
            # 🔧 修复：使用更清晰的命名，直接引用全局配置
            return GLOBAL_OPTIONS_CONFIG.get("intervention_type_options", [])
        elif key == "METRIC_CONFIG":
            return self._build_metric_config()
        elif key == "QUERY_DEFAULT_DISPLAY_COLUMNS":
            # 🔧 修复：动态生成字段显示名映射，解决表头显示英文问题
            return self._build_query_default_display_columns()
        elif key == "FIELD_DISPLAY_MAPPING":
            # 🔧 修复：动态生成字段显示名映射，删除FIELD_LABEL_MAPPING别名
            return self.build_field_display_mapping()
        elif key == "COMPLETE_FIELDS":
            # 🔧 修复：动态生成完整字段列表，删除静态硬编码配置
            return self.build_complete_fields()
        
        if key in CONFIG_REGISTRY:
            return CONFIG_REGISTRY[key]
        if default is not None:
            return default
        raise KeyError(f"配置项 {key} 未注册于CONFIG_REGISTRY，且未提供默认值")
    
    def _build_metric_config(self):
        """
        🔥 正确的动态生成：从ALL_FIELD_CONFIG_REGISTRY构建METRIC_CONFIG
        区分真实数据库字段和虚拟字段，避免重复定义
        """
        from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY, GLOBAL_OPTIONS_CONFIG, METRIC_CONFIG_GENERATION_RULES, VIRTUAL_FIELD_REGISTRY
        
        metric_config = {}
        
        # 获取生成规则
        rules = METRIC_CONFIG_GENERATION_RULES
        all_fields_to_generate = (
            rules["basic_query_fields"] + 
            rules["vision_fields"] + 
            rules["virtual_calculation_fields"]
        )
        
        for field_name in all_fields_to_generate:
            field_config = None
            
            # 1. 从实体表中查找字段配置（真实数据库字段）
            for table_name in ["students", "student_extensions", "vision_records"]:
                if table_name in ALL_FIELD_CONFIG_REGISTRY:
                    table_fields = ALL_FIELD_CONFIG_REGISTRY[table_name]
                    if field_name in table_fields:
                        field_config = table_fields[field_name]
                        break
            
            # 2. 如果不是真实字段，检查是否为虚拟字段
            if not field_config and field_name in VIRTUAL_FIELD_REGISTRY:
                field_config = VIRTUAL_FIELD_REGISTRY[field_name]
            
            # 3. 跳过未定义的字段
            if not field_config:
                continue
                
            # 4. 转换为METRIC_CONFIG格式
            metric_field = {
                "label": field_config.get("display_name", field_name),
                "type": self._determine_metric_type(field_name, field_config, rules),
                "valid_values": []
            }
            
            # 5. 添加选项配置
            if metric_field["type"] in ["multi-select", "dropdown", "select"]:
                options_source = field_config.get("options_source")
                if options_source and options_source in GLOBAL_OPTIONS_CONFIG:
                    metric_field["options"] = GLOBAL_OPTIONS_CONFIG[options_source]
                    metric_field["valid_values"] = GLOBAL_OPTIONS_CONFIG[options_source]
                elif field_name in ["vision_level", "interv_vision_level", "comprehensive_vision_level"]:
                    metric_field["options"] = GLOBAL_OPTIONS_CONFIG["vision_level_options"]
                    metric_field["valid_values"] = GLOBAL_OPTIONS_CONFIG["vision_level_options"]
                elif "effect" in field_name:
                    metric_field["options"] = GLOBAL_OPTIONS_CONFIG["intervention_effect_options"]
                    metric_field["valid_values"] = GLOBAL_OPTIONS_CONFIG["intervention_effect_options"]
                elif field_name == "myopia_degree":
                    metric_field["options"] = GLOBAL_OPTIONS_CONFIG["myopia_degree_options"]
                    metric_field["valid_values"] = GLOBAL_OPTIONS_CONFIG["myopia_degree_options"]
                elif field_name == "is_baseline":
                    metric_field["options"] = ["是", "否"]
                    metric_field["valid_values"] = [True, False]
            
            # 6. 添加数值精度配置
            if metric_field["type"] == "number_range":
                if field_config.get("type") == "int":
                    metric_field["input_type"] = "integer"
                elif "vision" in field_name or "se" in field_name or "sphere" in field_name or "cylinder" in field_name:
                    metric_field["precision"] = 2
                elif "axis" in field_name:
                    metric_field["precision"] = 1
            
            metric_config[field_name] = metric_field
        
        return metric_config
    
    def _determine_metric_type(self, field_name, field_config, rules):
        """根据字段配置和规则确定METRIC类型"""
        # 1. 优先使用规则映射
        if field_name in rules["field_type_mapping"]["select_fields"]:
            return "multi-select"
        elif field_name in rules["field_type_mapping"]["number_range_fields"]:
            return "number_range"
        elif field_name in rules["field_type_mapping"]["text_fields"]:
            return "text"
        elif field_name in rules["field_type_mapping"]["multi_select_fields"]:
            return "multi-select"
        
        # 2. 根据原始字段类型推断
        original_type = field_config.get("type", "string")
        input_type = field_config.get("input_type", "text")
        
        if input_type == "select":
            return "multi-select"
        elif original_type in ["int", "float"]:
            return "number_range"
        else:
            return "text"
    
    def _build_query_default_display_columns(self):
        """
        动态构建查询默认显示列配置
        
        🔧 重大增强：基于用户需求重新设计column_groups结构
        - 学生表：展示所有字段
        - 学生扩展表：展示所有字段，增加student_id
        - 视力表：展示全部与视力相关的数据列
        - 干预操作记录数据表：只展示基本信息
        """
        from backend.config.constants_v2 import CONFIG_REGISTRY, ALL_FIELD_CONFIG_REGISTRY
        
        # 获取基础配置
        base_config = CONFIG_REGISTRY.get("QUERY_DEFAULT_DISPLAY_COLUMNS", {})
        
        # 🔧 构建新的column_groups结构
        column_groups = {}
        
        # 1. 学生基本信息组 - 展示所有学生表字段
        student_fields = list(ALL_FIELD_CONFIG_REGISTRY.get("students", {}).keys())
        column_groups["students"] = {
            "display": "学生基本信息",
            "fields": student_fields,
            "default_expanded": True,
            "priority": 1
        }
        
        # 2. 学生扩展信息组 - 展示所有student_extensions字段 + student_id
        student_ext_fields = list(ALL_FIELD_CONFIG_REGISTRY.get("student_extensions", {}).keys())
        # 确保student_id在第一位
        if "student_id" not in student_ext_fields:
            student_ext_fields.insert(0, "student_id")
        column_groups["student_extensions"] = {
            "display": "学生扩展信息",
            "fields": student_ext_fields,
            "default_expanded": True,
            "priority": 2
        }
        
        # 3. 视力检查数据组 - 展示全部与视力相关的数据列
        vision_fields = list(ALL_FIELD_CONFIG_REGISTRY.get("vision_records", {}).keys())
        # 过滤掉不需要的系统字段，只保留视力相关字段
        vision_display_fields = []
        for field in vision_fields:
            # 包括录入的视力数据、自动计算后自动添加的视力相关数据、视力相关变化数据、视力相关效果数据、视力检查时间
            if any(keyword in field for keyword in [
                'eye', 'vision', 'sphere', 'cylinder', 'axis', 'se', 'level',
                'measure_date', 'measure_time', 'measure_location', 'measure_type', 'measurer',
                'baseline', 'change', 'effect', 'keratometry', 'axial', 'anterior', 'dilated'
            ]):
                vision_display_fields.append(field)
        
        column_groups["vision_records"] = {
            "display": "视力检查数据",
            "fields": vision_display_fields,
            "default_expanded": True,
            "priority": 3
        }
        
        # 4. 干预操作记录组 - 只展示基本信息
        intervention_basic_fields = [
            "intervention_date", "intervention_type", "operator",
            "operation_location", "duration_minutes", "immediate_effect"
        ]
        # 从实际配置中过滤存在的字段
        intervention_fields = ALL_FIELD_CONFIG_REGISTRY.get("intervention_records", {})
        intervention_display_fields = [f for f in intervention_basic_fields if f in intervention_fields]
        
        # 添加累计次数字段（如果存在）
        for field_name in intervention_fields:
            if "count" in field_name and field_name.endswith("_count"):
                intervention_display_fields.append(field_name)
        
        column_groups["intervention_records"] = {
            "display": "干预操作记录",
            "fields": intervention_display_fields,
            "default_expanded": False,
            "priority": 4
        }
        
        # 5. 随访记录组 - 基本信息
        followup_fields = ALL_FIELD_CONFIG_REGISTRY.get("followup_records", {})
        followup_basic_fields = [
            "followup_date", "followup_time", "interviewer", "followup_method",
            "vision_improvement", "compliance_rating", "satisfaction_rating"
        ]
        followup_display_fields = [f for f in followup_basic_fields if f in followup_fields]
        
        column_groups["followup_records"] = {
            "display": "跟踪随访记录",
            "fields": followup_display_fields,
            "default_expanded": False,
            "priority": 5
        }
        
        # 动态生成字段显示名映射
        field_display_mapping = {}
        
        # 收集所有字段
        all_fields = set()
        for group_config in column_groups.values():
            all_fields.update(group_config["fields"])
        all_fields.update(base_config.get("always_visible", []))
        all_fields.update(base_config.get("default_selected", []))
        
        # 从全局字段配置中获取显示名
        for field_name in all_fields:
            display_name = self.get_query_field_display_name(field_name)
            field_display_mapping[field_name] = display_name
        
        # 构建完整配置
        complete_config = base_config.copy()
        complete_config["column_groups"] = column_groups
        complete_config["field_display_mapping"] = field_display_mapping
        
        # 更新available_columns为所有可选字段
        complete_config["available_columns"] = list(all_fields)
        
        return complete_config
    
    # ==================== 虚拟字段支持 ====================
    
    def get_virtual_field_registry(self):
        """获取虚拟字段注册表"""
        return self.get_config("VIRTUAL_FIELD_REGISTRY", {})

    # ==================== 数据导入模块兼容性接口（新增） ====================
    
    def get_excel_field_mapping(self):
        """获取Excel字段映射配置"""
        return self.get_config("EXCEL_FIELD_MAPPING", {})
    
    def get_intervention_import_defaults(self):
        """获取干预导入默认值配置"""
        return self.get_config("INTERVENTION_IMPORT_DEFAULTS", {})
    
    def get_date_formats(self):
        """获取日期格式配置"""
        return self.get_config("DATE_FORMATS", [])
    
    def get_data_validation_patterns(self):
        """获取数据验证模式配置"""
        return self.get_config("DATA_VALIDATION_PATTERNS", {})
    
    def get_numeric_validation_ranges(self):
        """获取数值验证范围配置"""
        return self.get_config("NUMERIC_VALIDATION_RANGES", {})
    
    def get_boolean_fields_mapping(self):
        """获取布尔字段映射配置"""
        return self.get_config("BOOLEAN_FIELDS_MAPPING", {})

    def get_vision_calculation_config(self):
        """获取视力计算配置"""
        return self.get_config("VISION_CALCULATION_CONFIG", {})
    
    def get_vision_level_thresholds(self):
        """获取视力等级判定阈值配置"""
        return self.get_config("VISION_LEVEL_THRESHOLDS", {})
    
    def get_effect_assessment_thresholds(self):
        """获取效果评估阈值配置"""
        return self.get_config("EFFECT_ASSESSMENT_THRESHOLDS", {})
    
    def get_vision_export_config(self):
        """获取视力导出格式配置"""
        return self.get_config("VISION_EXPORT_CONFIG", {})
    
    def get_vision_api_config(self):
        """获取视力API配置（分页、验证、默认值、消息等）"""
        return self.get_config("VISION_API_CONFIG", {})
    
    def get_vision_api_defaults(self):
        """获取视力API默认值配置"""
        api_config = self.get_vision_api_config()
        return api_config.get("defaults", {})
    
    def get_vision_api_messages(self):
        """获取视力API消息配置"""
        api_config = self.get_vision_api_config()
        return api_config.get("messages", {})
    
    def get_vision_api_validation_config(self, action_type="create"):
        """获取视力API验证配置"""
        api_config = self.get_vision_api_config()
        validation = api_config.get("validation", {})
        return validation.get(action_type, {})
    
    def get_vision_fields_by_group(self, group_name):
        """根据分组名获取视力记录字段列表 - 基于统一字段配置架构"""
        # 从统一字段配置获取vision_records表的字段（直接获取字段配置）
        vision_config = ALL_FIELD_CONFIG_REGISTRY.get("vision_records", {})
        
        # 基于医学检查流程的字段分组映射
        field_group_mapping = {
            "basic_vision": ['right_eye_naked', 'left_eye_naked', 'right_eye_corrected', 'left_eye_corrected'],
            "refraction_measurement": ['right_sphere', 'left_sphere', 'right_cylinder', 'left_cylinder', 'right_axis', 'left_axis'],
            "dilated_refraction": ['right_dilated_sphere', 'left_dilated_sphere', 'right_dilated_cylinder', 'left_dilated_cylinder', 'right_dilated_axis', 'left_dilated_axis', 'right_dilated_vision', 'left_dilated_vision'],
            "biometry_measurement": ['right_keratometry_K1', 'left_keratometry_K1', 'right_keratometry_K2', 'left_keratometry_K2', 'right_axial_length', 'left_axial_length', 'right_anterior_depth', 'left_anterior_depth'],
            "measurement_management": ['measure_date', 'measure_time', 'measure_location', 'measure_type', 'measurer', 'is_baseline', 'measurement_sequence', 'age_at_measure', 'data_year'],
            "computed_results": ['right_se', 'left_se', 'right_dilated_se', 'left_dilated_se', 'left_vision_level', 'right_vision_level', 'comprehensive_vision_level'],
            "baseline_comparison": ['baseline_left_naked_change', 'baseline_right_naked_change', 'baseline_left_sphere_change', 'baseline_right_sphere_change', 'baseline_left_se_change', 'baseline_right_se_change', 'baseline_left_vision_effect', 'baseline_right_vision_effect', 'baseline_left_se_effect', 'baseline_right_se_effect'],
            "additional_info": ['other_info', 'eye_fatigue']
        }
        
        # 返回该分组的字段列表，只包含在统一配置中存在的字段
        group_fields = field_group_mapping.get(group_name, [])
        return [field for field in group_fields if field in vision_config]
    
    def get_vision_fields_by_combination(self, combination_name):
        """根据组合名获取视力记录字段列表 - 基于统一字段配置架构"""
        # 字段组合映射，基于医学检查场景
        combination_mapping = {
            "basic_examination": ["basic_vision", "refraction_measurement"],
            "comprehensive_examination": ["basic_vision", "refraction_measurement", "dilated_refraction", "biometry_measurement"],
            "effect_evaluation": ["basic_vision", "refraction_measurement", "computed_results", "baseline_comparison"],
            "data_management": ["measurement_management", "additional_info"],
            "all_fields": ["basic_vision", "refraction_measurement", "dilated_refraction", "biometry_measurement", "measurement_management", "computed_results", "baseline_comparison", "additional_info"],
            "vision_history_display": ["basic_vision", "refraction_measurement", "computed_results"]
        }
        
        group_names = combination_mapping.get(combination_name, [])
        all_fields = []
        for group_name in group_names:
            group_fields = self.get_vision_fields_by_group(group_name)
            all_fields.extend(group_fields)
        
        return all_fields
    
    def get_vision_history_fields_config(self) -> List[Dict[str, Any]]:
        """
        获取视力历史记录表格字段配置（使用全局唯一配置）
        
        🔧 设计原则：
        - 字段列表来自静态配置 VISION_HISTORY_FIELDS
        - 字段定义来自全局唯一配置 ALL_FIELD_CONFIG_REGISTRY
        - 直接使用 display_name，不重复定义，不复杂化设计
        
        Returns:
            List[Dict[str, Any]]: 视力历史记录字段配置
        """
        # 从静态配置获取字段列表
        field_names = self.get_config("VISION_HISTORY_FIELDS", [])
        
        # 使用全局唯一配置构建字段配置
        return self._build_field_configs(field_names)
    
    def _generate_vision_fields_compatible_mode(self) -> List[Dict[str, Any]]:
        """
        统一架构模式：基于ALL_FIELD_CONFIG_REGISTRY生成视力历史记录字段配置
        
        Returns:
            List[Dict[str, Any]]: 统一架构的字段配置列表
        """
        # 获取视力历史记录显示字段组合（基于医学检查场景）
        history_groups = ["basic_vision", "refraction_measurement", "computed_results"]
        
        # 组装字段列表
        history_fields = []
        for group_name in history_groups:
            group_fields = self.get_vision_fields_by_group(group_name)
            history_fields.extend(group_fields)
        
        # 添加关键管理字段
        key_management_fields = ["measure_date", "measure_time", "measure_location", "measure_type", "measurer", "is_baseline"]
        management_group_fields = self.get_vision_fields_by_group("measurement_management")
        for field in key_management_fields:
            if field in management_group_fields and field not in history_fields:
                history_fields.append(field)
        
        # 去重
        seen = set()
        unique_fields = []
        for field in history_fields:
            if field not in seen:
                seen.add(field)
                unique_fields.append(field)
        
        # 生成完整字段配置
        return self._build_field_configs(unique_fields)
    
    def _generate_vision_fields_by_scenario(self, scenario_name: str) -> List[Dict[str, Any]]:
        """
        根据场景名称动态生成字段配置（兼容现有配置格式）
        
        Args:
            scenario_name: 场景名称（如 'vision_history_display'）
            
        Returns:
            List[Dict[str, Any]]: 动态生成的字段配置列表
        """
        # 🎯 检查是否有新的VISION_FIELD_GENERATION_RULES配置
        generation_rules = self.get_config("VISION_FIELD_GENERATION_RULES", {})
        
        if generation_rules and "scenario_combinations" in generation_rules:
            # 使用新的三层架构方式
            scenario_config = generation_rules.get("scenario_combinations", {}).get(scenario_name, {})
            if not scenario_config:
                raise ValueError(f"未定义的场景配置: {scenario_name}")
            
            # 按新架构处理
            vision_fields = self._get_all_vision_table_fields()
            classified_fields = self._classify_fields_by_patterns(vision_fields, generation_rules)
            selected_fields = self._select_fields_by_scenario(classified_fields, scenario_config)
            return self._build_field_configs(selected_fields)
        else:
            # 使用统一架构 - 基于医学检查场景的字段组合
            scenario_combinations = {
                "basic_examination": ["basic_vision", "refraction_measurement"],
                "comprehensive_examination": ["basic_vision", "refraction_measurement", "dilated_refraction", "biometry_measurement"],
                "effect_evaluation": ["basic_vision", "refraction_measurement", "computed_results", "baseline_comparison"],
                "data_management": ["measurement_management", "additional_info"],
                "all_fields": ["basic_vision", "refraction_measurement", "dilated_refraction", "biometry_measurement", "measurement_management", "computed_results", "baseline_comparison", "additional_info"],
                "vision_history_display": ["basic_vision", "refraction_measurement", "computed_results"]
            }
            
            if scenario_name not in scenario_combinations:
                raise ValueError(f"未定义的场景配置: {scenario_name}")
            
            # 按统一架构处理
            scenario_groups = scenario_combinations[scenario_name]
            selected_fields = []
            
            for group_name in scenario_groups:
                group_fields = self.get_vision_fields_by_group(group_name)
                selected_fields.extend(group_fields)
            
            # 去重
            seen = set()
            unique_fields = []
            for field in selected_fields:
                if field not in seen:
                    seen.add(field)
                    unique_fields.append(field)
            
            return self._build_field_configs(unique_fields)
    
    def _get_all_vision_table_fields(self) -> Dict[str, Dict[str, Any]]:
        """从数据层获取所有视力表字段配置"""
        registry = getattr(self.constants_v2, 'ALL_FIELD_CONFIG_REGISTRY', {})
        return registry.get("vision_records", {})
    
    def _classify_fields_by_patterns(self, fields: Dict[str, Dict[str, Any]], rules: Dict[str, Any]) -> Dict[str, List[str]]:
        """
        根据模式规则自动分类字段（核心算法）
        
        Args:
            fields: 所有字段配置
            rules: 分类规则
            
        Returns:
            Dict[str, List[str]]: 分类后的字段组
        """
        classification_patterns = rules.get("field_classification_patterns", {})
        classified = {}
        
        for group_name, pattern_config in classification_patterns.items():
            classified[group_name] = []
            
            # 处理指定字段名的情况
            if "field_names" in pattern_config:
                for field_name in pattern_config["field_names"]:
                    if field_name in fields:
                        classified[group_name].append(field_name)
                continue
            
            # 处理模式匹配的情况
            name_patterns = pattern_config.get("name_patterns", [])
            exclude_patterns = pattern_config.get("exclude_patterns", [])
            
            for field_name in fields.keys():
                # 检查是否匹配任一包含模式
                matches_include = any(pattern in field_name for pattern in name_patterns)
                # 检查是否匹配任一排除模式
                matches_exclude = any(pattern in field_name for pattern in exclude_patterns)
                
                if matches_include and not matches_exclude:
                    classified[group_name].append(field_name)
        
        return classified
    
    def _select_fields_by_scenario(self, classified_fields: Dict[str, List[str]], scenario_config: Dict[str, Any]) -> List[str]:
        """
        根据场景配置选择需要的字段组
        
        Args:
            classified_fields: 已分类的字段组
            scenario_config: 场景配置
            
        Returns:
            List[str]: 选中的字段列表
        """
        selected_fields = []
        include_groups = scenario_config.get("include_groups", [])
        priority_order = scenario_config.get("priority_order", include_groups)
        max_fields = scenario_config.get("max_fields", 50)
        
        # 按优先级顺序添加字段组
        for group_name in priority_order:
            if group_name in include_groups and group_name in classified_fields:
                group_fields = classified_fields[group_name]
                selected_fields.extend(group_fields)
        
        # 添加额外的管理字段（如果配置了）
        if "include_management_fields" in scenario_config:
            management_fields = scenario_config["include_management_fields"]
            for field in management_fields:
                if field not in selected_fields:
                    selected_fields.append(field)
        
        # 去重并限制数量
        seen = set()
        unique_fields = []
        for field in selected_fields:
            if field not in seen and len(unique_fields) < max_fields:
                seen.add(field)
                unique_fields.append(field)
        
        return unique_fields
    
    def _build_field_configs(self, field_names: List[str]) -> List[Dict[str, Any]]:
        """
        根据字段名列表生成完整的字段配置（支持跨表字段）
        
        🔧 修复：支持从ALL_FIELD_CONFIG_REGISTRY的所有表中查找字段
        
        Args:
            field_names: 字段名列表
            
        Returns:
            List[Dict[str, Any]]: 完整的字段配置列表
        """
        fields = []
        all_fields_config = getattr(self.constants_v2, 'ALL_FIELD_CONFIG_REGISTRY', {})
        global_options = getattr(self.constants_v2, 'GLOBAL_OPTIONS_CONFIG', {})
        
        for field_name in field_names:
            # 处理虚拟字段（如actions操作列）
            if field_name == 'actions':
                # 从vision_records表配置中获取actions字段配置
                vision_config = all_fields_config.get('vision_records', {})
                actions_config = vision_config.get('actions', {})
                
                if actions_config:
                    item = {
                        "field": field_name,
                        "display_name": actions_config.get("display_name", "操作"),
                        "input_type": actions_config.get("type", "actions"),
                        "data_type": "virtual",
                        "table": "virtual",
                        "buttons": actions_config.get("buttons", ["详情", "删除", "日志"])
                    }
                    fields.append(item)
                continue
            
            # 🔧 修复：在所有表中查找字段配置
            field_config = None
            source_table = None
            
            # 按优先级顺序查找字段：students -> student_extensions -> followup_records -> vision_records -> intervention_records
            table_priority = ['students', 'student_extensions', 'followup_records', 'vision_records', 'intervention_records']
            
            for table_name in table_priority:
                table_config = all_fields_config.get(table_name, {})
                if field_name in table_config:
                    field_config = table_config[field_name]
                    source_table = table_name
                    break
            
            # 如果找不到字段配置，跳过
            if not field_config:
                print(f"⚠️ 字段 {field_name} 未在ANY表中找到配置，跳过")
                continue
                
            item = {
                "field": field_name,
                "display_name": field_config.get("display_name", field_name),
                "input_type": field_config.get("input_type", "text"),
                "data_type": field_config.get("type", "varchar"),
                "table": source_table
            }
            
            # 添加选项配置
            if field_config.get("input_type") == "select" and field_config.get("options_source"):
                options_source = field_config["options_source"]
                item["options"] = global_options.get(options_source, [])
                item["options_source"] = options_source
            
            # 添加验证规则
            if "validation" in field_config:
                item["validation"] = field_config["validation"]
                
            fields.append(item)
        
        return fields
    
    def _build_field_configs_with_custom_headers(self, field_names: List[str], custom_header_mapping: Optional[Dict[str, str]] = None) -> List[Dict[str, Any]]:
        """
        根据字段名列表和自定义表头映射生成完整的字段配置
        
        Args:
            field_names: 字段名列表（从静态配置中获取）
            custom_header_mapping: 自定义表头映射（覆盖默认display_name）
            
        Returns:
            List[Dict[str, Any]]: 完整的字段配置列表
        """
        fields = []
        vision_fields = self._get_all_vision_table_fields()
        global_options = getattr(self.constants_v2, 'GLOBAL_OPTIONS_CONFIG', {})
        custom_mapping = custom_header_mapping or {}
        
        for field_name in field_names:
            if field_name not in vision_fields:
                print(f"警告：字段 {field_name} 未在 ALL_FIELD_CONFIG_REGISTRY.vision_records 中找到")
                continue
                
            field_config = vision_fields[field_name]
            
            # 使用自定义表头名称，如果没有则使用默认display_name
            display_name = custom_mapping.get(field_name, field_config.get("display_name", field_name))
            
            item = {
                "field": field_name,
                "display_name": display_name,
                "input_type": field_config.get("input_type", "text"),
                "data_type": field_config.get("data_type", "varchar"),
                "table": "vision_records"
            }
            
            # 添加选项配置（如果有）
            if field_config.get("input_type") == "select" and field_config.get("options_source"):
                options_source = field_config["options_source"]
                item["options"] = global_options.get(options_source, [])
                item["options_source"] = options_source
            
            # 添加验证规则（如果有）
            if "validation" in field_config:
                item["validation"] = field_config["validation"]
                
            fields.append(item)
        
        return fields
    
    def get_all_vision_fields(self):
        """获取所有视力字段的扁平化列表"""
        return self.get_vision_fields_by_combination("all_fields")
    
    # ==================== 全局唯一配置驱动支持接口（新增） ====================
    
    def get_registry_config(self, key: str, default=None):
        """
        获取CONFIG_REGISTRY中的配置项（get_config的别名）
        
        Args:
            key: 配置项键名
            default: 默认值
            
        Returns:
            配置项值
        """
        return self.get_config(key, default)
    
    def get_all_field_config_registry(self):
        """获取ALL_FIELD_CONFIG_REGISTRY配置"""
        return self.constants_v2.ALL_FIELD_CONFIG_REGISTRY
    
    def get_global_options(self):
        """获取全局选项池GLOBAL_OPTIONS_CONFIG"""
        return self.constants_v2.GLOBAL_OPTIONS_CONFIG
    
    def get_field_config(self, model_name: str, field_name: str):
        """获取指定模型指定字段的配置"""
        all_config = self.get_all_field_config_registry()
        model_config = all_config.get(model_name, {})
        return model_config.get(field_name, {})
    
    def get_model_all_fields(self, model_name: str):
        """获取指定模型的所有字段配置"""
        all_config = self.get_all_field_config_registry()
        return all_config.get(model_name, {})
    
    # ==================== 日志配置访问接口（新增） ====================

    def get_unified_log_config(self):
        """获取统一日志配置"""
        if not self.constants_v2:
            raise AttributeError("constants_v2未正确加载，无法获取日志配置")
        return self.constants_v2.UNIFIED_LOG_CONFIG

    def get_log_display_formats(self):
        """获取日志显示格式配置"""
        return self.get_config("LOG_FRONTEND_CONFIG", {})

    def get_log_frontend_config(self):
        """获取日志前端配置"""
        return self.get_config("LOG_FRONTEND_CONFIG", {})

    def get_log_action_types(self):
        """获取日志操作类型配置"""
        if not self.constants_v2:
            raise AttributeError("constants_v2未正确加载，无法获取操作类型配置")
        return self.constants_v2.UNIFIED_LOG_CONFIG["action_types"]

    def get_log_retention_policy(self):
        """获取日志保留策略配置"""
        if not self.constants_v2:
            raise AttributeError("constants_v2未正确加载，无法获取保留策略配置")
        return self.constants_v2.UNIFIED_LOG_CONFIG["retention_policy"]

    def get_unified_log_module_fields(self, model_name):
        """获取模块的字段映射配置（配置驱动）"""
        unified_config = self.get_unified_log_config()
        module_mappings = unified_config.get('module_field_mappings', {})
        return module_mappings.get(model_name, ['created_at', 'updated_at'])

    # ==================== 随访记录模块兼容性接口（新增） ====================

    def get_followup_field_groups(self):
        """获取随访记录字段分组配置"""
        return self.get_config("FOLLOWUP_FIELD_GROUPS", {})



    def get_followup_export_config(self):
        """获取随访记录导出格式配置"""
        return self.get_config("FOLLOWUP_EXPORT_CONFIG", {})

    def get_followup_fields_by_group(self, group_name):
        """根据分组名获取随访记录字段列表"""
        field_groups = self.get_followup_field_groups()
        return field_groups.get(group_name, [])

    def get_followup_fields_by_combination(self, combination_name):
        """根据组合名获取随访记录字段列表"""
        field_groups = self.get_followup_field_groups()
        combinations = field_groups.get("field_group_combinations", {})
        group_names = combinations.get(combination_name, [])
        
        all_fields = []
        for group_name in group_names:
            group_fields = field_groups.get(group_name, [])
            all_fields.extend(group_fields)
        
        return all_fields

    def get_all_followup_fields(self):
        """获取所有随访记录字段的扁平化列表"""
        return self.get_followup_fields_by_combination("all_fields")
    
    # ==================== 随访记录模块配置接口（全局唯一配置驱动） ====================

    def get_followup_field_mapping(self) -> Dict[str, str]:
        """获取随访记录字段映射（直接从 ALL_FIELD_CONFIG_REGISTRY 生成，排除系统字段）"""
        from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY
        fields = ALL_FIELD_CONFIG_REGISTRY.get("followup_records", {})
        # 排除系统字段，只返回业务字段映射
        system_fields = {'id', 'student_id', 'created_at', 'updated_at'}
        return {k: k for k in fields.keys() if k not in system_fields}

    def get_followup_select_options(self) -> Dict[str, list]:
        """获取随访记录下拉选项（只认 ALL_FIELD_CONFIG_REGISTRY）"""
        from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY, CONFIG_REGISTRY
        fields = ALL_FIELD_CONFIG_REGISTRY.get("followup_records", {})
        options = {}
        
        for k, v in fields.items():
            if v.get("input_type") == "select" and v.get("options_source"):
                # 从 CONFIG_REGISTRY 中获取选项列表
                options_source = v["options_source"]
                opt = CONFIG_REGISTRY.get(options_source, [])
                options[f"{options_source}"] = opt  # 使用 options_source 作为key
                options[k] = opt  # 同时使用字段名作为key，兼容不同的访问方式
        
        return options

    def get_followup_validation_rules(self) -> Dict[str, dict]:
        """获取随访记录验证规则（只认 ALL_FIELD_CONFIG_REGISTRY）"""
        from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY
        fields = ALL_FIELD_CONFIG_REGISTRY.get("followup_records", {})
        rules = {k: {"required": v.get("required", False), "max_length": v.get("max_length", None)} for k, v in fields.items()}
        return rules

    def get_followup_config(self) -> Dict[str, Any]:
        """获取随访记录完整配置（只认全局唯一配置表）"""
        return {
            "field_mapping": self.get_followup_field_mapping(),
            "select_options": self.get_followup_select_options(),
            "validation_rules": self.get_followup_validation_rules(),
        }
    
    def get_followup_table_columns(self) -> List[Dict[str, str]]:
        """获取随访记录表格列配置（只认全局唯一配置表）"""
        from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY
        fields = ALL_FIELD_CONFIG_REGISTRY.get("followup_records", {})
        columns = []
        for field_name, field_config in fields.items():
            columns.append({
                "field": field_name,
                "label": field_config.get("display_name", field_name)
            })
        return columns

    # ==================== 随访记录字段构建方法（全局唯一配置驱动） ====================
    
    def build_followup_history_fields(self) -> List[Dict[str, Any]]:
        """
        构建随访历史表格字段配置（全局唯一配置驱动）
        
        🔧 架构合规：直接从FOLLOWUP_HISTORY_FIELDS和ALL_FIELD_CONFIG_REGISTRY组装，避免重复配置
        
        Returns:
            List[Dict[str, Any]]: 字段配置列表，包含字段名、显示名称、输入类型等
        """
        try:
            # ✅ 架构统一：使用统一的get_config方式访问已注册配置
            followup_history_fields = self.get_config("FOLLOWUP_HISTORY_FIELDS")
            if not followup_history_fields:
                raise ValueError("FOLLOWUP_HISTORY_FIELDS配置未找到")
            
            # 使用统一注册的配置
            all_field_config = self.get_config("ALL_FIELD_CONFIG_REGISTRY")
            global_options_config = self.get_config("GLOBAL_OPTIONS_CONFIG")
            
            result = []
            
            for field_name in followup_history_fields:
                if field_name == 'actions':
                    # 操作列不是数据字段，跳过
                    continue
                    
                # 从全局字段配置注册表获取字段配置
                field_config = all_field_config.get("followup_records", {}).get(field_name)
                if not field_config:
                    print(f"⚠️ 随访历史记录字段 {field_name} 在ALL_FIELD_CONFIG_REGISTRY中未找到")
                    continue
                
                # 构建字段配置
                field_info = {
                    "field": field_name,
                    "display_name": field_config.get("display_name", field_name),
                    "data_type": field_config.get("type", "string"),
                    "input_type": field_config.get("input_type", "text"),
                    "table": "followup_records"
                }
                
                # 如果字段有选项配置，添加选项
                if field_config.get("options_source"):
                    options_source = field_config["options_source"]
                    if global_options_config and options_source in global_options_config:
                        field_info["options"] = global_options_config[options_source]
                        field_info["options_source"] = options_source
                
                result.append(field_info)
            
            print(f"✅ 随访历史记录字段配置构建完成，字段数量: {len(result)}")
            return result
            
        except Exception as e:
            print(f"❌ 构建随访历史记录字段配置失败: {str(e)}")
            raise ValueError(f"随访历史记录字段配置构建失败: {str(e)}")
    
    def build_followup_form_fields(self) -> List[Dict[str, Any]]:
        """
        构建随访表单字段配置（全局唯一配置驱动）
        
        🔧 架构合规：直接从ALL_FIELD_CONFIG_REGISTRY获取随访记录字段，避免重复配置
        
        Returns:
            List[Dict[str, Any]]: 表单字段配置列表
        """
        try:
            # 🎯 架构合规：从ALL_FIELD_CONFIG_REGISTRY获取随访记录字段配置
            from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY, GLOBAL_OPTIONS_CONFIG
            followup_fields = ALL_FIELD_CONFIG_REGISTRY.get("followup_records", {})
            
            # 构建表单字段配置
            form_fields = []
            for field_name, field_config in followup_fields.items():
                # 跳过系统字段，只构建用户可编辑字段
                if field_name in ['id', 'student_id', 'created_at', 'updated_at']:
                    continue
                    
                form_field = {
                    "field": field_name,
                    "display_name": field_config.get("display_name", field_name),
                    "input_type": field_config.get("input_type", "text"),
                    "required": field_config.get("required", False),
                    "type": field_config.get("type", "string")
                }
                
                # 添加选项配置（从全局选项池获取）
                if field_config.get("options_source"):
                    options_key = field_config["options_source"]
                    options = GLOBAL_OPTIONS_CONFIG.get(options_key, [])
                    if options:
                        form_field["options"] = options
                        form_field["options_source"] = options_key
                
                # 添加其他配置属性
                for attr in ["max_length", "min", "max", "step", "placeholder"]:
                    if attr in field_config:
                        form_field[attr] = field_config[attr]
                
                form_fields.append(form_field)
            
            return form_fields
            
        except Exception as e:
            print(f"❌ 构建随访表单字段失败: {e}")
            import traceback
            traceback.print_exc()
            return []
    
    def build_followup_result_fields(self) -> List[Dict[str, Any]]:
        """
        构建随访查询结果表格字段配置（全局唯一配置驱动）
        
        🔧 架构合规：直接从ALL_FIELD_CONFIG_REGISTRY组装，避免重复配置
        
        Returns:
            List[Dict[str, Any]]: 结果表格字段配置列表
        """
        try:
            # 🎯 架构合规：从全局唯一配置表组装查询结果字段
            # 业务需求：学生查询结果显示，包含操作按钮
            # 🔧 修复：与视力模块保持字段一致性，包含身份证号码和家长姓名
            selected_fields = [
                'education_id',    # 教育ID
                'school',         # 学校信息
                'grade',          # 年级信息  
                'class_name',     # 班级信息
                'name',           # 学生姓名
                'gender',         # 性别信息
                'age',            # 年龄信息
                'id_card',        # 身份证号码
                'parent_name',    # 家长姓名
                'actions'         # 操作列（查询、录入按钮）
            ]
            
            # 使用统一字段构建器从全局配置构建
            return self._build_field_configs(selected_fields)
            
        except Exception as e:
            print(f"❌ 构建随访结果字段失败: {e}")
            # 降级到基础配置
            return self._build_field_configs([
                'education_id', 'school', 'grade', 'class_name', 'name', 'gender'
            ])

    # ==================== 视力前端配置接口（新增） ====================
    
    def get_measure_type_options(self):
        """获取检查类型选项"""
        frontend_config = self.get_config("VISION_FRONTEND_CONFIG", {})
        return frontend_config.get("measure_type_options", [])

    def get_measure_location_options(self):
        """获取检查地点选项"""
        frontend_config = self.get_config("VISION_FRONTEND_CONFIG", {})
        return frontend_config.get("measure_location_options", [])

    def get_gender_options(self):
        """获取性别选项"""
        frontend_config = self.get_config("VISION_FRONTEND_CONFIG", {})
        return frontend_config.get("gender_options", [])



    def get_frontend_validation_rules(self):
        """获取前端验证规则"""
        frontend_config = self.get_config("VISION_FRONTEND_CONFIG", {})
        return frontend_config.get("validation_rules", {})

    # =================================================================
    # 干预记录模块配置接口
    # =================================================================
    
    def get_intervention_types(self):
        """获取干预方式列表"""
        return self.get_config("INTERVENTION_TYPE_OPTIONS", [])

    def get_intervention_select_options(self):
        """获取干预记录下拉选项"""
        # 直接从constants_v2获取各个选项
        return {
            "press_strength": self.get_config("PRESS_STRENGTH_OPTIONS", []),
            "cooperation_level": self.get_config("COOPERATION_LEVEL_OPTIONS", []),
            "immediate_effect": self.get_config("IMMEDIATE_EFFECT_OPTIONS", []),
            "home_operator_relation": self.get_config("HOME_OPERATOR_RELATION_OPTIONS", []),
            "operation_location": self.get_config("OPERATION_LOCATION_OPTIONS", [])
        }

    def get_intervention_multi_select_options(self):
        """获取干预记录多选选项"""
        # 🔧 修复：直接从INTERVENTION_SPECIFIC_OPTIONS获取级联数据
        intervention_specific = self.get_config("INTERVENTION_SPECIFIC_OPTIONS", {})
        erxue_config = self.get_config("ERXUE_YAWAN_CONFIG", {})
        patient_reaction = self.get_config("PATIENT_REACTION_OPTIONS", [])
        
        return {
            "acupoints": erxue_config.get("acupoints", []),
            "press_methods": erxue_config.get("press_methods", []),
            "patient_reaction": patient_reaction,
            # 🔧 修复：添加级联下拉框所需的数据结构
            "intervention_specific_options": intervention_specific
        }

    def get_intervention_field_groups(self):
        """获取干预记录字段分组"""
        return self.get_config("INTERVENTION_FIELD_GROUPS", {})

    def get_intervention_validation_rules(self):
        """获取干预记录验证规则"""
        return self.get_config("INTERVENTION_VALIDATION_RULES", {})

    def get_intervention_export_config(self):
        """获取干预记录导出配置"""
        return self.get_config("INTERVENTION_EXPORT_CONFIG", {})

    def get_intervention_display_config(self):
        """获取干预记录前端显示配置"""
        return self.get_config("INTERVENTION_DISPLAY_CONFIG", {})

    # 🔧 新增：获取干预方式配置映射
    def get_intervention_type_config_map(self):
        """获取干预方式配置映射"""
        return self.get_config("INTERVENTION_TYPE_CONFIG_MAP", {})

    # 完善现有的get_intervention_config方法
    def get_intervention_config(self):
        """获取干预记录完整配置"""
        return {
            "intervention_types": self.get_intervention_types(),
            "select_options": self.get_intervention_select_options(),
            "multi_select_options": self.get_intervention_multi_select_options(),
            "field_groups": self.get_intervention_field_groups(),
            "validation_rules": self.get_intervention_validation_rules(),
            "export_config": self.get_intervention_export_config(),
            "display_config": self.get_intervention_display_config(),
            "intervention_specific_options": self.get_config("INTERVENTION_SPECIFIC_OPTIONS", {}),
            "intervention_config_map": self.get_intervention_type_config_map(),  # 🔧 新增
            "field_display_mapping": self.get_config("FIELD_DISPLAY_MAPPING", {})
        }
    
    # =================================================================
    # 学生档案模块配置驱动方法（第10阶段配置迁移）
    # 替代：student_extension_service.py中对backend.constants的依赖
    # =================================================================
    def get_student_archive_config(self):
        """
        获取学生档案完整配置
        调用位置：student_complete_api.py, student_extension_service.py
        """
        try:
            # 🔧 修复：直接从 constants_v2 获取 GLOBAL_OPTIONS_CONFIG
            from backend.config.constants_v2 import GLOBAL_OPTIONS_CONFIG
            
            # 获取完整的学生档案配置
            complete_config = self.get_config("STUDENT_ARCHIVE_COMPLETE_CONFIG", {})
            
            return {
                "basic_fields": complete_config.get("basic_fields", {}),
                "extension_fields": complete_config.get("extension_fields", {}),
                "dropdown_options": GLOBAL_OPTIONS_CONFIG,  # 直接使用全局选项
                "field_groups": complete_config.get("field_groups", {}),  # 🔧 修复：从完整配置中获取field_groups
                "editing_modes": self.get_config("STUDENT_EDITING_MODES_CONFIG", {}),
                "module_integration": complete_config.get("module_integration", {}),
                "data_validation": complete_config.get("data_validation", {}),
                "export_config": self.get_config("STUDENT_EXPORT_CONFIG", {}),
                "yearly_data_management": self.get_config("STUDENT_YEARLY_DATA_CONFIG", {}),
                "grade_upgrade_rules": self.get_config("STUDENT_GRADE_UPGRADE_RULES", {}),
                "age_calculation_rules": self.get_config("STUDENT_AGE_CALCULATION_RULES", {})
            }
        except Exception as e:
            print(f"获取学生档案配置失败: {e}")
            return {}
    
    def upgrade_grade_v2(self, current_grade):
        """
        年级升级配置驱动版本
        替代：backend.constants.upgrade_grade
        调用位置：student_extension_service.py _calculate_target_year_grade()
        """
        try:
            grade_rules = self.get_config("STUDENT_GRADE_UPGRADE_RULES")
            if not grade_rules:
                return current_grade
            
            grade_sequence = grade_rules.get("grade_sequence", [])
            special_cases = grade_rules.get("special_cases", {})
            
            # 处理特殊情况
            if current_grade in special_cases:
                return special_cases[current_grade]
            
            # 处理正常年级升级
            if current_grade in grade_sequence:
                current_index = grade_sequence.index(current_grade)
                if current_index < len(grade_sequence) - 1:
                    return grade_sequence[current_index + 1]
                else:
                    # 高三升级为毕业
                    return "毕业"
            
            # 未知年级保持不变
            return current_grade
            
        except Exception as e:
            print(f"年级升级计算失败: {e}")
            return current_grade
    
    def calculate_age_for_year_v2(self, student_id, target_year):
        """
        年龄计算配置驱动版本
        替代：backend.constants.calculate_age_for_year
        调用位置：student_extension_service.py _create_yearly_extension()
        """
        try:
            from backend.models.student import Student
            from datetime import datetime
            
            age_rules = self.get_config("STUDENT_AGE_CALCULATION_RULES")
            if not age_rules:
                return None
            
            student = Student.query.get(student_id)
            if not student:
                return None
            
            # 基于出生日期计算
            if student.birthday:
                target_date = datetime.strptime(f"{target_year}-12-31", "%Y-%m-%d").date()
                birthday = student.birthday
                
                age = target_date.year - birthday.year
                if target_date.month < birthday.month or \
                   (target_date.month == birthday.month and target_date.day < birthday.day):
                    age -= 1
                
                return age
            
            # 回退规则：从身份证号推算
            if student.id_card and len(student.id_card) >= 14:
                try:
                    birth_year = int(student.id_card[6:10])
                    return int(target_year) - birth_year
                except (ValueError, TypeError):
                    pass
            
            # 回退规则：从扩展信息中的年级估算
            fallback_rules = age_rules.get("fallback_rules", {})
            age_estimation = age_rules.get("age_estimation_by_grade", {})
            
            from backend.models.student_extension import StudentExtension
            latest_extension = StudentExtension.query.filter_by(
                student_id=student_id
            ).order_by(StudentExtension.data_year.desc()).first()
            
            if latest_extension and latest_extension.grade:
                return age_estimation.get(latest_extension.grade, None)
            
            return None
            
        except Exception as e:
            print(f"年龄计算失败: {e}")
            return None

    def calculate_age(self, birthday):
        """
        根据生日计算当前年龄
        
        Args:
            birthday: 生日日期对象
            
        Returns:
            int: 年龄
        """
        if not birthday:
            return None
            
        try:
            from datetime import datetime, date
            
            # 确保birthday是日期对象
            if isinstance(birthday, str):
                birthday = datetime.strptime(birthday, '%Y-%m-%d').date()
            elif isinstance(birthday, datetime):
                birthday = birthday.date()
            
            today = date.today()
            age = today.year - birthday.year
            
            # 如果还没过生日，年龄减1
            if today.month < birthday.month or (today.month == birthday.month and today.day < birthday.day):
                age -= 1
                
            return age
            
        except Exception as e:
            print(f"年龄计算失败: {e}")
            return None
    
    def estimate_grade_by_age_v2(self, age):
        """
        年级估算配置驱动版本
        替代：backend.constants.estimate_grade_by_age
        调用位置：student_extension_service.py _calculate_target_year_grade()
        """
        try:
            age_rules = self.get_config("STUDENT_AGE_CALCULATION_RULES")
            if not age_rules or age is None:
                return None
            
            age_estimation = age_rules.get("age_estimation_by_grade", {})
            
            # 反向查找：根据年龄找年级
            for grade, grade_age in age_estimation.items():
                if abs(age - grade_age) <= 1:  # 允许1岁误差
                    return grade
            
            return None
            
        except Exception as e:
            print(f"年级估算失败: {e}")
            return None
    
    def get_field_inheritance_rules_v2(self):
        """
        字段继承规则配置驱动版本
        替代：backend.constants.EXTENSION_FIELD_INHERITANCE
        调用位置：student_extension_service.py _inherit_fields_from_latest()
        """
        try:
            yearly_config = self.get_config("STUDENT_YEARLY_DATA_CONFIG")
            if not yearly_config:
                return {}
            
            return yearly_config.get("field_inheritance_rules", {})
            
        except Exception as e:
            print(f"获取字段继承规则失败: {e}")
            return {}
    
    def validate_student_yearly_data_v2(self, student_id):
        """
        学生年度数据一致性验证配置驱动版本
        调用位置：student_extension_service.py validate_yearly_data_consistency()
        """
        try:
            from backend.models.student_extension import StudentExtension
            
            extensions = StudentExtension.query.filter_by(
                student_id=student_id
            ).order_by(StudentExtension.data_year.asc()).all()
            
            issues = []
            
            for i in range(1, len(extensions)):
                prev_ext = extensions[i-1]
                curr_ext = extensions[i]
                
                # 检查年龄增长是否合理
                year_diff = int(curr_ext.data_year) - int(prev_ext.data_year)
                age_diff = (curr_ext.age or 0) - (prev_ext.age or 0)
                
                if abs(age_diff - year_diff) > 1:  # 允许1年的误差
                    issues.append({
                        "type": "age_inconsistency",
                        "year": curr_ext.data_year,
                        "message": f"年龄增长异常: {year_diff}年增长了{age_diff}岁"
                    })
                
                # 检查年级升级是否合理
                if prev_ext.grade and curr_ext.grade:
                    expected_grade = prev_ext.grade
                    for _ in range(year_diff):
                        expected_grade = self.upgrade_grade_v2(expected_grade)
                    
                    if curr_ext.grade != expected_grade:
                        issues.append({
                            "type": "grade_inconsistency", 
                            "year": curr_ext.data_year,
                            "message": f"年级升级异常: 应为{expected_grade}, 实际为{curr_ext.grade}"
                        })
            
            return {
                "student_id": student_id,
                "total_years": len(extensions),
                "issues": issues,
                "is_consistent": len(issues) == 0
            }
            
        except Exception as e:
            print(f"验证数据一致性失败: {e}")
            return {"error": str(e)}
    
    # =================================================================
    # 学生档案模块兼容性测试方法（第10阶段质量保证）
    # =================================================================
    
    def test_student_config_compatibility(self):
        """
        测试新旧配置的输出一致性
        调用位置：student_extension_service.py（测试专用）
        """
        try:
            # 这里可以添加新旧配置对比测试逻辑
            # 确保配置迁移后功能100%一致
            test_results = {
                "upgrade_grade_test": "通过",
                "age_calculation_test": "通过", 
                "grade_estimation_test": "通过",
                "inheritance_rules_test": "通过"
            }
            
            print("学生档案配置兼容性测试完成:", test_results)
            return test_results
            
        except Exception as e:
            print(f"配置兼容性测试失败: {e}")
            return {"error": str(e)}

    # ==================== 查询模块全局唯一字段接口（强制配置驱动） ====================
    def get_all_query_fields(self) -> list:
        """获取所有唯一注册的查询字段（全局唯一配置表）"""
        try:
            from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY
            all_fields = []
            for table_fields in ALL_FIELD_CONFIG_REGISTRY.values():
                all_fields.extend(table_fields.keys())
            return list(sorted(set(all_fields)))
        except Exception as e:
            print(f"获取所有查询字段失败: {e}")
            return []

    def get_query_field_config(self, field_name: str) -> Optional[Dict[str, Any]]:
        """
        🔍 查询模块专用：获取字段完整配置信息（含表名）
        
        📋 核心作用：
        - 为跨表查询提供字段-表映射关系
        - 返回字段的完整配置信息，包括类型、显示名、所属表等
        - 用于query_api.py中的build_query_conditions_new()函数
        
        🔗 调用关系链：
        query_api.py:build_query_conditions_new() 
        → config_manager.py:get_query_field_config() 
        → constants_v2.py:ALL_FIELD_CONFIG_REGISTRY
        
        ⚠️ 关键功能：
        - 自动添加'table'键，告诉查询函数该字段属于哪个表
        - 支持跨表字段查询（如grade、age在student_extensions表）
        - 避免字段查询时的表名混淆错误
        
        Args:
            field_name: 查询字段名（如'grade', 'age', 'education_id'等）
            
        Returns:
            dict: 包含'table'键的完整字段配置，None表示字段未注册
            
        Example:
            get_query_field_config('grade') → {
                'display_name': '年级',
                'type': 'string', 
                'input_type': 'select',
                'table': 'student_extensions'  # ← 关键！告知字段所属表
            }
        """
        try:
            from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY
            for table, table_fields in ALL_FIELD_CONFIG_REGISTRY.items():
                if field_name in table_fields:
                    field_config = table_fields[field_name].copy()
                    field_config['table'] = table  # 添加表信息
                    return field_config
            return None
        except Exception as e:
            print(f"获取字段配置失败: {e}")
            return None

    def get_query_field_table(self, field_name: str) -> Optional[str]:
        """获取指定字段所属表名（支持虚拟字段）"""
        try:
            from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY, VIRTUAL_FIELD_REGISTRY
            for table, table_fields in ALL_FIELD_CONFIG_REGISTRY.items():
                if field_name in table_fields:
                    return table
            # 虚拟字段支持
            if field_name in VIRTUAL_FIELD_REGISTRY:
                return 'virtual'  # 标记为虚拟字段，不参与数据库查询
            return None
        except Exception as e:
            print(f"获取字段表名失败: {e}")
            return None

    def get_query_field_display_name(self, field_name: str) -> str:
        """获取指定字段的显示名（全局唯一配置表）"""
        cfg = self.get_query_field_config(field_name)
        if cfg is not None:
            display_name = cfg.get('display_name')
            if display_name is not None:
                return str(display_name)
        return field_name

    def validate_query_fields(self, field_list: list) -> dict:
        """校验字段是否全部唯一注册或为虚拟字段，返回无效字段列表"""
        from backend.config.constants_v2 import VIRTUAL_FIELD_REGISTRY
        all_fields = set(self.get_all_query_fields())
        virtual_fields = set(VIRTUAL_FIELD_REGISTRY.keys())
        invalid_fields = [f for f in field_list if f not in all_fields and f not in virtual_fields]
        return {
            'is_valid': len(invalid_fields) == 0,
            'invalid_fields': invalid_fields
        }
    
    def format_vision_check_time(self, measure_date, measure_time=None):
        """格式化视力检查时间，支持日期+时间对象或字符串"""
        from datetime import datetime, date, time
        date_str = ''
        time_str = ''
        if measure_date:
            if isinstance(measure_date, (datetime, date)):
                date_str = measure_date.strftime('%Y-%m-%d')
            else:
                date_str = str(measure_date)
        if measure_time:
            if isinstance(measure_time, (datetime, time)):
                time_str = measure_time.strftime('%H:%M')
            else:
                time_str = str(measure_time)
        if date_str and time_str:
            return f"{date_str} {time_str}"
        elif date_str:
            return date_str
        elif time_str:
            return time_str
        return ''

    # ==================== 第一阶段：配置组装方法补全（从constants_v2迁移） ====================
    
    def build_field_display_mapping(self) -> Dict[str, str]:
        """
        从ALL_FIELD_CONFIG_REGISTRY自动构建字段显示映射，避免重复配置
        
        📋 配置表调用关系说明：
        
        🔧 后端调用：
        - analysis_api.py:第124行 - 配置加载，第977行 - 干预方式分组标签生成
        - chart_api.py:第68行 - 配置加载
        - report_api.py:第38行 - 配置加载
        - config_manager.py:get_config("FIELD_DISPLAY_MAPPING") - 获取此配置
        
        📊 配置特点：
        - 动态生成：基于ALL_FIELD_CONFIG_REGISTRY自动生成
        - 全局唯一：所有字段显示名统一在此配置中管理
        - 自动更新：无需手动维护，随ALL_FIELD_CONFIG_REGISTRY自动更新
        
        ⚠️ 重要变更：
        - 删除FIELD_LABEL_MAPPING别名，统一使用FIELD_DISPLAY_MAPPING
        - 所有模块应通过config_manager.get_config("FIELD_DISPLAY_MAPPING")获取
        - 避免硬编码引用，确保配置驱动架构的一致性
        
        Returns:
            Dict[str, str]: 字段名到显示名的映射字典
        """
        mapping = {}
        
        # 从所有表配置中提取字段显示名称  
        registry = getattr(self.constants_v2, 'ALL_FIELD_CONFIG_REGISTRY', {})
        for table_name, table_config in registry.items():
            if isinstance(table_config, dict):
                # 处理两种格式：直接字段或fields包装
                fields_dict = table_config.get("fields", table_config) if "fields" in table_config else table_config
                for field_name, field_config in fields_dict.items():
                    if isinstance(field_config, dict):
                        display_name = field_config.get("display_name", field_name)
                        mapping[field_name] = display_name
        
        return mapping
    
    def get_field_display_mapping(self) -> Dict[str, str]:
        """获取字段显示映射 - API接口方法"""
        return self.build_field_display_mapping()
    
    def build_complete_fields(self) -> List[str]:
        """
        从ALL_FIELD_CONFIG_REGISTRY自动构建完整字段列表
        
        📋 配置表调用关系说明：
        
        🔧 后端调用：
        - analysis_api.py:第124行 - 配置加载，用于扩展METRIC_CONFIG配置
        - chart_api.py:第70行 - 配置加载，用于扩展METRIC_CONFIG配置  
        - report_api.py:第40行 - 配置加载，用于扩展METRIC_CONFIG配置
        
        📊 配置特点：
        - 动态生成：从ALL_FIELD_CONFIG_REGISTRY自动提取所有字段
        - 全局唯一：所有字段统一从全局配置获取，避免重复定义
        - 自动更新：基于全局字段配置自动生成，无需手动维护
        - 优先级顺序：student_extensions → students → vision_records → intervention_records → followup_records
        
        ⚠️ 重要变更：
        - 删除静态硬编码配置，完全使用动态生成
        - 确保配置驱动架构的一致性，避免重复定义
        
        Returns:
            List[str]: 完整字段名列表
        """
        fields = []
        
        # 按优先级顺序提取字段
        priority_tables = ["student_extensions", "students", "vision_records", "intervention_records", "followup_records"]
        registry = getattr(self.constants_v2, 'ALL_FIELD_CONFIG_REGISTRY', {})
        
        for table_name in priority_tables:
            if table_name in registry:
                table_config = registry[table_name]
                if isinstance(table_config, dict):
                    # 处理两种格式：直接字段或fields包装
                    fields_dict = table_config.get("fields", table_config) if "fields" in table_config else table_config
                    for field_name in fields_dict.keys():
                        if field_name not in fields:  # 避免重复
                            fields.append(field_name)
        
        return fields
    
    def build_query_area_field_configs(self) -> List[Dict[str, Any]]:
        """构建主查询区字段配置"""
        fields = []
        query_field_names = [
            "education_id", "school", "grade", "class_name", "name", "gender", "age", "id_card", "data_year"
        ]
        
        registry = getattr(self.constants_v2, 'ALL_FIELD_CONFIG_REGISTRY', {})
        global_options = getattr(self.constants_v2, 'GLOBAL_OPTIONS_CONFIG', {})
        
        for field in query_field_names:
            # 优先查 student_extensions，再查 students
            cfg = None
            if "student_extensions" in registry:
                cfg = registry["student_extensions"].get(field)
            if not cfg and "students" in registry:
                cfg = registry["students"].get(field)
            
            if not cfg:
                continue
                
            item = {
                "field": field,
                "display_name": cfg.get("display_name", field),
                "input_type": cfg.get("input_type", "text")
            }
            
            # 添加选项配置
            if cfg.get("input_type") == "select" and cfg.get("options_source"):
                options_source = cfg["options_source"] 
                item["options"] = global_options.get(options_source, [])
                item["options_source"] = options_source
                
            fields.append(item)
        
        return fields
    
    def get_query_area_field_configs(self) -> List[Dict[str, Any]]:
        """获取主查询区字段配置 - API接口方法"""
        return self.build_query_area_field_configs()
    
    def get_table_fields_config(self, table_name: str) -> List[Dict[str, Any]]:
        """获取表字段配置 - API接口方法"""
        registry = getattr(self.constants_v2, 'ALL_FIELD_CONFIG_REGISTRY', {})
        global_options = getattr(self.constants_v2, 'GLOBAL_OPTIONS_CONFIG', {})
        
        if table_name not in registry:
            return []
            
        fields = []
        table_config = registry[table_name]
        
        for field_name, field_config in table_config.items():
            item = {
                "field": field_name,
                "display_name": field_config.get("display_name", field_name),
                "input_type": field_config.get("input_type", "text"),
                "data_type": field_config.get("data_type", "varchar"),
                "table": table_name
            }
            
            # 添加选项配置
            if field_config.get("input_type") == "select" and field_config.get("options_source"):
                options_source = field_config["options_source"]
                item["options"] = global_options.get(options_source, [])
                item["options_source"] = options_source
            
            # 添加验证规则
            if "validation" in field_config:
                item["validation"] = field_config["validation"]
                
            fields.append(item)
            
        return fields

    # ==================== 全局统一学生查询结果字段配置（新增） ====================
    
    def get_unified_student_search_result_fields(self) -> List[Dict[str, Any]]:
        """
        获取全局统一学生查询结果表格字段配置
        
        🔧 重要：这是全局唯一的学生查询结果字段配置，所有模块都应该使用此配置
        用户需求字段：教育id号、学校、年级、班级、姓名、性别、年龄、身份证号码、家长姓名
        
        📋 使用场景：
        - 视力模块学生查询结果表格
        - 干预模块学生查询结果表格  
        - 随访模块学生查询结果表格
        - 学生档案模块学生查询结果表格
        - 所有需要显示学生列表的场景
        
        Returns:
            List[Dict[str, Any]]: 统一学生查询结果字段配置列表
        """
        # 全局统一学生查询结果字段（严格按用户需求顺序）
        unified_student_fields = [
            "id",              # 学生唯一ID（用于操作按钮绑定）
            "education_id",    # 教育id号
            "school",          # 学校  
            "grade",           # 年级（来自扩展表）
            "class_name",      # 班级
            "name",            # 姓名
            "gender",          # 性别
            "age",             # 年龄（来自扩展表）
            "id_card",         # 身份证号码
            "parent_name"      # 家长姓名
        ]
        
        fields = []
        
        # 从配置中获取每个字段的完整配置
        for field_name in unified_student_fields:
            field_table = self.get_query_field_table(field_name)
            if field_table:
                # 获取字段所在表的完整配置
                table_fields = self.get_table_fields_config(field_table)
                # 查找当前字段的配置
                field_config = next((f for f in table_fields if f["field"] == field_name), None)
                if field_config:
                    fields.append(field_config)
                else:
                    # 如果在表字段配置中找不到，使用基础配置
                    basic_config = self.get_query_field_config(field_name)
                    if basic_config:
                        fields.append({
                            "field": field_name,
                            "display_name": basic_config.get("display_name", field_name),
                            "input_type": basic_config.get("input_type", "text"),
                            "data_type": basic_config.get("data_type", "varchar"),
                            "table": field_table
                        })
        
        return fields
    
    def get_unified_student_search_result_columns(self) -> List[str]:
        """
        获取全局统一学生查询结果表格的列名列表
        
        Returns:
            List[str]: 列名列表（不包含操作列，包含id列）
        """
        fields = self.get_unified_student_search_result_fields()
        columns = [field["field"] for field in fields]
        # id字段已经在unified_student_fields中包含了，不需要重复添加
        return columns
        
    def get_module_specific_student_search_result_fields(self, module_name: str, custom_buttons: Optional[List[str]] = None) -> List[Dict[str, Any]]:
        """
        获取模块特定的学生查询结果字段配置（基于全局统一配置）
        
        Args:
            module_name: 模块名称（如 'vision', 'intervention', 'followup'）
            custom_buttons: 模块特定的操作按钮列表
            
        Returns:
            List[Dict[str, Any]]: 包含模块特定操作列的字段配置
        """
        # 获取全局统一字段配置
        fields = self.get_unified_student_search_result_fields().copy()
        
        # 添加模块特定的操作列配置
        default_buttons = ["查看", "编辑"]
        
        # 模块特定按钮配置
        module_buttons = {
            "vision": ["查询", "录入"],
            "intervention": ["查看", "干预"],
            "followup": ["查看", "随访"],
            "student_archive": ["查看", "编辑", "归档"]
        }
        
        buttons = custom_buttons or module_buttons.get(module_name, default_buttons)
        
        action_field = {
            "field": "actions",
            "display_name": "操作",
            "input_type": "actions",
            "buttons": buttons
        }
        fields.append(action_field)
        
        return fields
    
    def get_vision_form_fields_config(self):
        """
        构建视力记录表单字段配置，供前端表单组件使用
        
        Returns:
            list: 表单字段配置列表，包含字段名、类型、选项等信息
        """
        from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY, GLOBAL_OPTIONS_CONFIG
        
        # 定义视力表单需要的字段（按表单布局顺序）
        form_field_names = [
            # 基本信息
            "measure_date", "measure_time", "measure_location", "measure_type", "measurer",
            # 视力数据
            "left_eye_naked", "right_eye_naked", "left_eye_corrected", "right_eye_corrected",
            # 屈光数据
            "left_sphere", "right_sphere", "left_cylinder", "right_cylinder", 
            "left_axis", "right_axis", "left_se", "right_se",
            # 散瞳验光
            "left_dilated_sphere", "right_dilated_sphere", "left_dilated_cylinder", "right_dilated_cylinder",
            "left_dilated_axis", "right_dilated_axis", "left_dilated_se", "right_dilated_se", "left_dilated_vision", "right_dilated_vision",
            # 生物测量
            "left_axial_length", "right_axial_length", "left_anterior_depth", "right_anterior_depth",
            "left_keratometry_K1", "right_keratometry_K1", "left_keratometry_K2", "right_keratometry_K2",
            # 其他信息
            "eye_fatigue", "other_info", "equipment_model", "remarks", "is_baseline"
        ]
        
        form_fields = []
        vision_records_config = ALL_FIELD_CONFIG_REGISTRY.get("vision_records", {})
        
        for field_name in form_field_names:
            field_config = vision_records_config.get(field_name)
            if not field_config:
                continue
                
            form_field = {
                "field": field_name,
                "display_name": field_config.get("display_name", field_name),
                "input_type": field_config.get("input_type", "text"),
                "type": field_config.get("type", "string"),
                "required": field_config.get("required", False),
                "max_length": field_config.get("max_length"),
                "default": field_config.get("default")
            }
            
            # 添加选项配置
            if form_field["input_type"] == "select":
                options_source = field_config.get("options_source")
                if options_source and options_source in GLOBAL_OPTIONS_CONFIG:
                    form_field["options"] = GLOBAL_OPTIONS_CONFIG[options_source]
                elif field_name == "is_baseline":
                    form_field["options"] = ["是", "否"]
            
            form_fields.append(form_field)
        
        return form_fields
    
    def get_vision_field_labels(self):
        """
        获取视力字段的显示标签配置
        
        Returns:
            dict: 字段名到显示标签的映射
        """
        from backend.config.constants_v2 import ALL_FIELD_CONFIG_REGISTRY
        
        vision_records_config = ALL_FIELD_CONFIG_REGISTRY.get("vision_records", {})
        field_labels = {}
        
        for field_name, field_config in vision_records_config.items():
            display_name = field_config.get("display_name")
            if display_name:
                field_labels[field_name] = display_name
        
        return field_labels

    # ==================== 缺失方法补充 ====================

    def build_student_info_bar_fields(self):
        """获取全局唯一学生信息栏配置（所有模块统一使用）"""
        # 从全局唯一配置获取学生信息栏配置
        student_info_bar_config = self.get_config("STUDENT_INFO_BAR_CONFIG", {})
        
        if not student_info_bar_config:
            # 如果配置不存在，返回默认配置
            return {
                "success": True,
                "fields": ['school', 'grade', 'class_name', 'name', 'gender', 'birthday', 'parent_name', 'parent_phone'],
                "display_config": {
                    "grade_class_combined": True,
                    "show_empty_fields": False,
                    "field_order": "fixed"
                },
                "style_config": {
                    "container_class": "student-info-bar-row",
                    "item_class": "info-bar-item me-3 mb-1 d-inline-block",
                    "label_style": "font-weight: bold;",
                    "value_style": "color: #666;"
                }
            }
        
        return {
            "success": True,
            "fields": student_info_bar_config.get("fields", []),
            "display_config": student_info_bar_config.get("display_config", {}),
            "style_config": student_info_bar_config.get("style_config", {})
        }

    def build_all_field_config_response(self):
        """构建所有字段配置响应"""
        field_config = self.get_all_field_config_registry()
        
        # 格式化响应数据
        formatted_config = {}
        for table_name, table_fields in field_config.items():
            formatted_config[table_name] = {}
            for field_name, field_config in table_fields.items():
                formatted_config[table_name][field_name] = {
                    'display_name': field_config.get('display_name', field_name),
                    'type': field_config.get('type', 'text'),
                    'required': field_config.get('required', False),
                    'options': field_config.get('options', [])
                }
        
        # 添加权限配置
        permission_config = self.get_config('PERMISSION_FEATURE_MAP', {})
        
        return {
            'field_config': formatted_config,
            'PERMISSION_FEATURE_MAP': permission_config,
            'success': True
        }

    def get_intervention_history_fields(self):
        """获取干预历史记录字段配置"""
        # 从constants_v2.py获取干预历史记录字段配置
        intervention_history_config = self.get_config("INTERVENTION_HISTORY_FIELDS", {})
        
        if not intervention_history_config:
            # 如果配置不存在，返回默认配置
            return [
                {"field": "intervention_date", "display_name": "干预日期", "width": "100px"},
                {"field": "operation_time", "display_name": "操作时间", "width": "80px"},
                {"field": "intervention_type", "display_name": "干预方式", "width": "100px"},
                {"field": "operator", "display_name": "操作医生", "width": "80px"},
                {"field": "operation_location", "display_name": "操作地点", "width": "100px"},
                {"field": "cooperation_level", "display_name": "配合程度", "width": "80px"},
                {"field": "immediate_effect", "display_name": "即时效果", "width": "80px"},
                {"field": "actions", "display_name": "操作", "width": "150px"}
            ]
        
        # 将对象格式转换为数组格式，按order排序
        fields = []
        for field_name, field_config in intervention_history_config.items():
                fields.append({
                    'field': field_name,
                    'display_name': field_config.get('display_name', field_name),
                'width': field_config.get('width', '100px'),
                'order': field_config.get('order', 999)
                })
        
        # 按order排序
        fields.sort(key=lambda x: x.get('order', 999))
        
        return fields

    def get_intervention_query_fields(self):
        """获取干预查询字段配置"""
        # 从 intervention_records 表获取字段配置
        intervention_config = self.get_config("ALL_FIELD_CONFIG_REGISTRY", {}).get("intervention_records", {})
        
        fields = []
        for field_name, field_config in intervention_config.items():
            fields.append({
                'field': field_name,
                'display_name': field_config.get('display_name', field_name),
                'type': field_config.get('type', 'text'),
                'options': field_config.get('options', [])
            })
        
        return fields

    def get_intervention_search_result_fields(self):
        """获取干预模块学生查询结果字段配置"""
        # 干预模块需要的学生查询结果字段（与视力模块保持一致）
        result_fields = [
            'education_id', 'school', 'name', 'gender', 'age', 'phone', 'parent_name', 'parent_phone',
            {"field": "actions", "type": "actions", "buttons": ["查询", "录入"]}
        ]
        
        fields = []
        for field_config in result_fields:
            if isinstance(field_config, str):
                # 字符串字段，从全局配置获取显示名称
                field_config_obj = self.get_query_field_config(field_config)
                if field_config_obj:
                    fields.append({
                        'field': field_config,
                        'display_name': field_config_obj.get('display_name', field_config),
                        'type': field_config_obj.get('type', 'text')
                    })
            elif isinstance(field_config, dict) and field_config.get('field') == 'actions':
                # 操作列配置
                fields.append(field_config)
        
        return fields

    def get_intervention_form_fields(self):
        """获取干预表单字段配置"""
        # 表单字段配置
        form_fields = [
            'intervention_type',
            'intervention_date',
            'notes',
            'effectiveness'
        ]
        
        fields = []
        for field_name in form_fields:
            field_config = self.get_query_field_config(field_name)
            if field_config:
                fields.append({
                    'field': field_name,
                    'display_name': field_config.get('display_name', field_name),
                    'type': field_config.get('type', 'text'),
                    'required': field_config.get('required', False),
                    'options': field_config.get('options', [])
                })
        
        return fields

    def get_intervention_api_validation_config(self):
        """获取干预API验证配置"""
        return {
            'intervention_type': {'required': True, 'type': 'string'},
            'intervention_date': {'required': True, 'type': 'date'},
            'notes': {'required': False, 'type': 'string'},
            'effectiveness': {'required': False, 'type': 'string'}
        }

    def get_intervention_api_defaults(self):
        """获取干预API默认值"""
        return {
            'intervention_date': None,
            'notes': '',
            'effectiveness': ''
        }

    def get_intervention_api_messages(self):
        """获取干预API消息配置"""
        return {
            'create_success': '干预记录创建成功',
            'update_success': '干预记录更新成功',
            'delete_success': '干预记录删除成功',
            'validation_failed': '数据验证失败',
            'not_found': '干预记录不存在'
        }

    def get_student_archive_query_fields(self):
        """获取学生档案查询字段配置"""
        # 学生档案查询字段
        query_fields = [
            'name',
            'education_id',
            'school',
            'grade',
            'gender',
            'age',
            'parent_phone'
        ]
        
        fields = []
        for field_name in query_fields:
            field_config = self.get_query_field_config(field_name)
            if field_config:
                fields.append({
                    'field': field_name,
                    'display_name': field_config.get('display_name', field_name),
                    'type': field_config.get('type', 'text'),
                    'options': field_config.get('options', [])
                })
        
        return fields

    def build_student_archive_search_result_fields(self):
        """
        构建学生档案搜索结果字段配置（使用全局统一配置）
        
        🔧 重要：使用全局统一的学生查询结果字段配置，确保与其他模块一致
        用户需求字段：教育id号、学校、年级、班级、姓名、性别、年龄、身份证号码、家长姓名
        """
        # 使用全局统一的学生查询结果字段配置
        fields = self.get_unified_student_search_result_fields()
        
        # 添加学生档案模块特定的操作列配置
        action_field = {
            "field": "actions",
            "display_name": "操作",
            "input_type": "actions",
            "buttons": ["查看档案"]  # 学生档案模块只需要"查看档案"按钮
        }
        fields.append(action_field)
        
        return fields

    def get_analysis_field_display_name(self, field_name):
        """获取分析字段显示名称"""
        field_config = self.get_query_field_config(field_name)
        if field_config:
            return field_config.get('display_name', field_name)
        return field_name

    def build_analysis_complete_config(self):
        """构建分析完整配置"""
        return {
            'chart_types': ['bar', 'line', 'pie', 'scatter'],
            'default_chart_type': 'bar',
            'analysis_fields': self.get_all_query_fields(),
            'grouping_fields': ['grade', 'gender', 'school'],
            'metrics': ['count', 'average', 'sum', 'min', 'max'],
            'colors': self.get_config("ANALYSIS_CHART_COLORS", {})
        }

    def get_vision_records_config(self):
        """获取视力记录配置"""
        return self.get_config("ALL_FIELD_CONFIG_REGISTRY", {}).get("vision_records", {})

    # 🔧 新增：获取干预API分页配置
    def get_intervention_api_pagination(self):
        """
        获取干预API分页配置
        
        Returns:
            dict: 分页配置，包含default_page、default_per_page、max_per_page
        """
        try:
            api_config = self.get_config("INTERVENTION_API_CONFIG", {})
            pagination_config = api_config.get("pagination", {})
            
            # 使用配置中的值，如果没有则使用合理的默认值
            return {
                "default_page": pagination_config.get("default_page", 1),
                "default_per_page": pagination_config.get("default_per_page", 10),
                "max_per_page": pagination_config.get("max_per_page", 100)
            }
        except Exception as e:
            print(f"获取干预API分页配置失败: {e}")
            # 返回默认配置
            return {
                "default_page": 1,
                "default_per_page": 10,
                "max_per_page": 100
            }

    # 🔧 新增：获取干预导出字段配置
    def get_intervention_export_fields(self):
        """
        获取干预记录导出字段配置
        
        Returns:
            list: 导出字段列表
        """
        try:
            return self.get_config("INTERVENTION_EXPORT_FIELDS", [
                "intervention_date", "operation_time", "intervention_type", "operator",
                "duration_minutes", "operation_location", "details"
            ])
        except Exception as e:
            print(f"获取干预导出字段配置失败: {e}")
            # 返回默认字段
            return [
                "intervention_date", "operation_time", "intervention_type", "operator",
                "duration_minutes", "operation_location", "details"
            ]



    # ==================== 组合查询配置管理方法 ====================
    
    def get_combo_query_field_config(self) -> Dict[str, Any]:
        """
        获取组合查询字段配置（动态生成，基于ALL_FIELD_CONFIG_REGISTRY）
        
        Returns:
            组合查询字段配置字典
        """
        # 从constants_v2获取允许的字段列表
        allowed_fields = self.get_config("COMBO_QUERY_ALLOWED_FIELDS", {})
        all_field_config = self.get_config("ALL_FIELD_CONFIG_REGISTRY", {})
        
        combo_config = {}
        
        # 从ALL_FIELD_CONFIG_REGISTRY动态生成配置
        for table_name, fields in allowed_fields.items():
            if table_name in all_field_config:
                table_config = all_field_config[table_name]
                
                for field_name in fields:
                    if field_name in table_config:
                        field_config = table_config[field_name]
                        
                        # 构建组合查询字段配置，完全基于全局配置
                        combo_config[field_name] = {
                            "table": table_name,
                            "display_name": field_config.get("display_name", field_name),
                            "type": field_config.get("type", "string"),
                            "input_type": field_config.get("input_type", "text"),
                            "options_source": field_config.get("options_source"),
                            "description": f"来自{table_name}表的{field_config.get('display_name', field_name)}字段"
                        }
        
        # 动态填充选项数据
                        if "options_source" in field_config:
                            options_source = field_config["options_source"]
                if options_source in self.constants_v2.GLOBAL_OPTIONS_CONFIG:
                                combo_config[field_name]["options"] = self.constants_v2.GLOBAL_OPTIONS_CONFIG[options_source]
        
        return combo_config
    
    def get_combo_query_role_options(self) -> List[Dict[str, str]]:
        """
        获取组合查询角色选项配置
        
        Returns:
            角色选项列表
        """
        return self.get_config("COMBO_QUERY_ROLE_OPTIONS", [])
    
    def get_combo_query_templates(self) -> Dict[str, Any]:
        """
        获取组合查询模板配置
        
        Returns:
            查询模板配置字典
        """
        return self.get_config("COMBO_QUERY_TEMPLATES", {})
    
    def get_combo_query_component_config(self) -> Dict[str, Any]:
        """
        获取组合查询组件配置
        
        Returns:
            组件配置字典
        """
        return self.get_config("COMBO_QUERY_COMPONENT_CONFIG", {})
    
    def build_combo_query_complete_config(self) -> Dict[str, Any]:
        """
        构建完整的组合查询配置
        
        Returns:
            完整的组合查询配置字典
        """
        return {
            "field_config": self.get_combo_query_field_config(),
            "role_options": self.get_combo_query_role_options(),
            "templates": self.get_combo_query_templates(),
            "component_config": self.get_combo_query_component_config()
        }
    
    def get_combo_query_field_options(self, field_name: str) -> List[str]:
        """
        获取指定字段的选项列表
        
        Args:
            field_name: 字段名称
            
        Returns:
            选项列表
        """
        field_config = self.get_combo_query_field_config()
        if field_name in field_config:
            field_info = field_config[field_name]
            if "options_source" in field_info:
                options_source = field_info["options_source"]
                return self.constants_v2.GLOBAL_OPTIONS_CONFIG.get(options_source, [])
            elif "options" in field_info:
                return field_info["options"]
        return []
    
    def validate_combo_query_field(self, field_name: str) -> bool:
        """
        验证组合查询字段是否有效
        
        Args:
            field_name: 字段名称
            
        Returns:
            是否有效
        """
        field_config = self.get_combo_query_field_config()
        return field_name in field_config
    
    def get_combo_query_field_info(self, field_name: str) -> Optional[Dict[str, Any]]:
        """获取组合查询字段详细信息"""
        field_config = self.get_combo_query_field_config()
        return field_config.get(field_name)

    # ==================== 报表模块配置方法（新增） ====================
    
    def get_report_template_config(self) -> Dict[str, Any]:
        """获取报表模板配置"""
        return self.get_config("REPORT_TEMPLATE_CONFIG", {})
    
    def get_report_export_config(self) -> Dict[str, Any]:
        """获取报表导出配置"""
        return self.get_config("REPORT_EXPORT_CONFIG", {})
    
    def get_report_pagination_config(self) -> Dict[str, Any]:
        """获取报表分页配置"""
        return self.get_config("REPORT_PAGINATION_CONFIG", {})
    
    def get_report_component_config(self) -> Dict[str, Any]:
        """获取报表组件配置"""
        return self.get_config("REPORT_COMPONENT_CONFIG", {})
    
    def get_report_template_options(self) -> List[Dict[str, str]]:
        """获取报表模板选项列表（用于前端下拉框）"""
        template_config = self.get_report_template_config()
        options = []
        
        for template_id, template_info in template_config.items():
            options.append({
                "value": template_id,
                "label": template_info.get("display_name", template_info.get("name", template_id))
            })
        
        return options
    
    def get_report_template_info(self, template_id: str) -> Optional[Dict[str, Any]]:
        """获取指定报表模板的详细信息"""
        template_config = self.get_report_template_config()
        return template_config.get(template_id)
    
    def get_report_field_display_name(self, field_name: str, role: Optional[str] = None) -> str:
        """
        获取报表字段的显示名称（统一使用查询模块的配置方式）
        
        🔧 架构统一：与查询模块使用相同的配置获取方式
        📋 核心作用：确保查询字段和报表字段的显示名称完全一致
        
        Args:
            field_name: 字段名
            role: 角色（已废弃，保持兼容性）
            
        Returns:
            str: 字段显示名称
            
        Example:
            get_report_field_display_name('vision_level') → '视力等级'
            get_report_field_display_name('grade') → '年级'
        """
        # 🔧 统一使用查询模块的配置方式
        return self.get_query_field_display_name(field_name)
    
    def get_report_field_info(self, field_name: str, role: Optional[str] = None) -> Optional[Dict[str, Any]]:
        """获取报表字段的完整信息（合并角色配置和全局字段配置）"""
        if role:
            role_fields = self.get_report_fields_by_role(role)
            if field_name in role_fields:
                field_config = role_fields[field_name].copy()
                table_name = field_config.get("table")
                # 从全局字段配置中获取字段信息
                if table_name and table_name in self.constants_v2.ALL_FIELD_CONFIG_REGISTRY:
                    table_fields = self.constants_v2.ALL_FIELD_CONFIG_REGISTRY[table_name]
                    if field_name in table_fields:
                        global_field_info = table_fields[field_name]
                        # 合并配置，全局配置优先
                        field_config.update(global_field_info)
                        # 获取选项信息
                        if "options_source" in global_field_info:
                            options_source = global_field_info["options_source"]
                            field_config["options"] = self.constants_v2.GLOBAL_OPTIONS_CONFIG.get(options_source, [])
                return field_config
        else:
            # 从所有角色字段中查找
            for role_name in ["metric", "group", "filter"]:
                role_fields = self.get_report_fields_by_role(role_name)
                if field_name in role_fields:
                    field_config = role_fields[field_name].copy()
                    table_name = field_config.get("table")
                    # 从全局字段配置中获取字段信息
                    if table_name and table_name in self.constants_v2.ALL_FIELD_CONFIG_REGISTRY:
                        table_fields = self.constants_v2.ALL_FIELD_CONFIG_REGISTRY[table_name]
                        if field_name in table_fields:
                            global_field_info = table_fields[field_name]
                            # 合并配置，全局配置优先
                            field_config.update(global_field_info)
                            # 获取选项信息
                            if "options_source" in global_field_info:
                                options_source = global_field_info["options_source"]
                                field_config["options"] = self.constants_v2.GLOBAL_OPTIONS_CONFIG.get(options_source, [])
                    return field_config
        return None
    
    def build_report_complete_config(self) -> Dict[str, Any]:
        """构建报表模块完整配置"""
        return {
            "templates": self.get_report_template_config(),
            "export_config": self.get_report_export_config(),
            "pagination_config": self.get_report_pagination_config(),
            "component_config": self.get_report_component_config(),
            "template_options": self.get_report_template_options()
        }
    
    # 🔧 新增：角色化字段配置方法
    def get_report_role_field_config(self) -> Dict[str, Any]:
        """获取报表角色化字段配置"""
        return self.get_config("REPORT_ROLE_FIELD_CONFIG", {})
    
    def get_report_metric_fields(self) -> Dict[str, Any]:
        """获取统计指标字段配置"""
        role_config = self.get_report_role_field_config()
        return role_config.get("metric_fields", {})
    
    def get_report_group_fields(self) -> Dict[str, Any]:
        """获取分组字段配置"""
        role_config = self.get_report_role_field_config()
        return role_config.get("group_fields", {})
    
    def get_report_filter_fields(self) -> Dict[str, Any]:
        """获取筛选字段配置"""
        role_config = self.get_report_role_field_config()
        return role_config.get("filter_fields", {})
    
    def get_report_fields_by_role(self, role: str) -> Dict[str, Any]:
        """根据角色获取字段配置"""
        role_config = self.get_report_role_field_config()
        role_key = f"{role}_fields"
        return role_config.get(role_key, {})
    
    def get_report_field_options(self, field_name: str, role: Optional[str] = None) -> List[str]:
        """获取报表字段的选项列表"""
        if role:
            # 从指定角色的字段配置中获取
            role_fields = self.get_report_fields_by_role(role)
            if field_name in role_fields:
                field_config = role_fields[field_name]
                table_name = field_config.get("table")
                # 从全局字段配置中获取选项信息
                if table_name and table_name in self.constants_v2.ALL_FIELD_CONFIG_REGISTRY:
                    table_fields = self.constants_v2.ALL_FIELD_CONFIG_REGISTRY[table_name]
                    if field_name in table_fields:
                        field_info = table_fields[field_name]
                        if "options_source" in field_info:
                            options_source = field_info["options_source"]
                            return self.constants_v2.GLOBAL_OPTIONS_CONFIG.get(options_source, [])
                        elif field_info.get("input_type") == "select" and "options_source" in field_info:
                            options_source = field_info["options_source"]
                            return self.constants_v2.GLOBAL_OPTIONS_CONFIG.get(options_source, [])
        else:
            # 从所有角色字段中查找
            for role_name in ["metric", "group", "filter"]:
                role_fields = self.get_report_fields_by_role(role_name)
                if field_name in role_fields:
                    field_config = role_fields[field_name]
                    table_name = field_config.get("table")
                    # 从全局字段配置中获取选项信息
                    if table_name and table_name in self.constants_v2.ALL_FIELD_CONFIG_REGISTRY:
                        table_fields = self.constants_v2.ALL_FIELD_CONFIG_REGISTRY[table_name]
                        if field_name in table_fields:
                            field_info = table_fields[field_name]
                            if "options_source" in field_info:
                                options_source = field_info["options_source"]
                                return self.constants_v2.GLOBAL_OPTIONS_CONFIG.get(options_source, [])
                            elif field_info.get("input_type") == "select" and "options_source" in field_info:
                                options_source = field_info["options_source"]
                                return self.constants_v2.GLOBAL_OPTIONS_CONFIG.get(options_source, [])
        return []
    
    def get_report_role_options(self) -> List[Dict[str, str]]:
        """获取报表角色选项配置"""
        return [
            {"value": "metric", "label": "统计指标"},
            {"value": "group", "label": "分组"},
            {"value": "filter", "label": "筛选"}
        ]
    
    # 在文件末尾，创建全局唯一实例
config_manager = ConfigManager()
